import React, { useState, useEffect, useRef } from 'react';
import { Button } from "./ui/button";
import { useLanguage } from "~/lib/LanguageContext";
import AIChatStream from './ai-chat-stream';
import Prism from 'prismjs';
import MarkdownViewer from './markdown-viewer';

// 导入Prism主题和语言，你可以选择其他主题
import 'prismjs/themes/prism-tomorrow.css';
// 基础语言
import 'prismjs/components/prism-javascript';
import 'prismjs/components/prism-typescript';
import 'prismjs/components/prism-css';
import 'prismjs/components/prism-markup'; // HTML
import 'prismjs/components/prism-jsx';
import 'prismjs/components/prism-tsx';
// 后端语言
import 'prismjs/components/prism-python';
import 'prismjs/components/prism-java';
import 'prismjs/components/prism-c';
import 'prismjs/components/prism-cpp';
import 'prismjs/components/prism-csharp';
import 'prismjs/components/prism-go';
import 'prismjs/components/prism-rust';
// 数据格式
import 'prismjs/components/prism-json';
import 'prismjs/components/prism-yaml';
import 'prismjs/components/prism-markdown';
// 配置文件
import 'prismjs/components/prism-bash';
import 'prismjs/components/prism-docker';

interface CodeViewerProps {
  fileUrl: string;
  onClose?: () => void;
  repoUrl?: string;
}

export default function CodeViewer({ fileUrl, onClose, repoUrl }: CodeViewerProps) {
  const { t } = useLanguage();
  const [code, setCode] = useState<string>('');
  const [loading, setLoading] = useState<boolean>(true);
  const [error, setError] = useState<string>('');
  const [showAiChat, setShowAiChat] = useState<boolean>(false);
  const [language, setLanguage] = useState<string>('');
  const [isMarkdown, setIsMarkdown] = useState<boolean>(false);
  const codeRef = useRef<HTMLElement>(null);
  
  // 根据文件扩展名获取语言
  const getLanguageFromFilename = (filename: string): string => {
    const extension = filename.split('.').pop()?.toLowerCase() || '';
    
    // 检查是否为Markdown文件
    if (extension === 'md' || extension === 'markdown') {
      setIsMarkdown(true);
    }
    
    const extensionMap: Record<string, string> = {
      js: 'javascript',
      jsx: 'jsx',
      ts: 'typescript',
      tsx: 'tsx',
      html: 'markup',
      css: 'css',
      scss: 'scss',
      py: 'python',
      java: 'java',
      c: 'c',
      cpp: 'cpp',
      cs: 'csharp',
      go: 'go',
      rs: 'rust',
      json: 'json',
      yml: 'yaml',
      yaml: 'yaml',
      md: 'markdown',
      sh: 'bash',
      dockerfile: 'docker',
      // 可以继续添加更多扩展名
    };
    
    return extensionMap[extension] || '';
  };
  
  useEffect(() => {
    // 从GitHub获取代码
    async function fetchCode() {
      // 当URL为空时不执行
      if (!fileUrl) {
        setLoading(false);
        setError('未指定文件URL');
        return;
      }
      
      try {
        setLoading(true);
        
        // 把GitHub网页URL转换为API URL
        // 例如：https://github.com/username/repo/blob/master/path/to/file.js
        // 变为：https://api.github.com/repos/username/repo/contents/path/to/file.js
        
        // 从URL中提取用户名、仓库名和文件路径
        const githubRegex = /github\.com\/([^/]+)\/([^/]+)\/blob\/[^/]+\/(.+)/;
        const match = fileUrl.match(githubRegex);
        
        if (!match) {
          throw new Error('无效的GitHub文件URL');
        }
        
        const [, username, repo, filePath] = match;
        const apiUrl = `https://api.github.com/repos/${username}/${repo}/contents/${filePath}`;
        
        // 检查是否有GitHub PAT
        const githubPat = localStorage.getItem('github_pat');
        const headers: HeadersInit = {};
        
        if (githubPat) {
          headers.Authorization = `token ${githubPat}`;
        }
        
        const response = await fetch(apiUrl, { headers });
        
        if (!response.ok) {
          throw new Error(`获取代码失败: ${response.status} ${response.statusText}`);
        }
        
        const data = await response.json();
        
        // GitHub API返回Base64编码的内容
        if (data.content && data.encoding === 'base64') {
          const decodedContent = atob(data.content.replace(/\n/g, ''));
          setCode(decodedContent);
          
          // 根据文件名设置语言
          const fileName = filePath ? filePath.split('/').pop() || '' : '';
          const detectedLanguage = getLanguageFromFilename(fileName);
          setLanguage(detectedLanguage);
        } else {
          throw new Error('未找到文件内容或格式不受支持');
        }
      } catch (err) {
        console.error('获取代码出错:', err);
        setError(err instanceof Error ? err.message : '获取代码时出错');
      } finally {
        setLoading(false);
      }
    }
    
    void fetchCode();
  }, [fileUrl]);
  
  // 应用语法高亮
  useEffect(() => {
    if (code && language && codeRef.current) {
      // 异步应用高亮以避免性能问题
      setTimeout(() => {
        if (codeRef.current) {
          // 确保元素存在
          Prism.highlightElement(codeRef.current);
        }
      }, 0);
    }
  }, [code, language, codeRef]);
  
  // 复制代码到剪贴板
  const handleCopyCode = async () => {
    try {
      await navigator.clipboard.writeText(code);
      // 可以添加复制成功提示
    } catch (err) {
      console.error('复制代码失败:', err);
    }
  };
  
  // 获取文件名
  const fileName = fileUrl.split('/').pop() || '';
  
  return (
    <div className="flex flex-col w-full h-full border-2 border-gray-200 rounded-lg bg-white dark:bg-gray-900 dark:border-gray-700 shadow-lg">
      <div className="flex justify-between items-center border-b p-4 dark:border-gray-700">
        <h3 className="font-semibold text-lg truncate flex-1">
          {fileName}
        </h3>
        <div className="flex space-x-2">
          <Button
            onClick={handleCopyCode}
            disabled={!code || loading}
            className="border-[2px] border-black bg-gray-200 px-3 py-1 text-black shadow-[3px_3px_0_0_#000000] transition-transform hover:-translate-x-0.5 hover:-translate-y-0.5 hover:bg-gray-300 dark:border-gray-700 dark:bg-gray-700 dark:text-white dark:shadow-[3px_3px_0_0_#1f1f1f] dark:hover:bg-gray-600"
            size="sm"
          >
            {t("copy")}
          </Button>
          <Button
            onClick={() => setShowAiChat(!showAiChat)}
            className="border-[2px] border-black bg-blue-400 px-3 py-1 text-black shadow-[3px_3px_0_0_#000000] transition-transform hover:-translate-x-0.5 hover:-translate-y-0.5 hover:bg-blue-300 dark:border-gray-700 dark:bg-blue-600 dark:text-white dark:shadow-[3px_3px_0_0_#1f1f1f] dark:hover:bg-blue-500"
            size="sm"
          >
            {showAiChat ? t("close") : t("ai_chat")}
          </Button>
          {onClose && (
            <button 
              onClick={onClose}
              className="ml-2 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"
            >
              ✕
            </button>
          )}
        </div>
      </div>
      
      <div className="flex flex-1 overflow-hidden">
        <div className={`flex-1 transition-all ${showAiChat ? 'w-1/2' : 'w-full'}`}>
          {loading ? (
            <div className="flex justify-center items-center h-full p-4">
              <div className="w-8 h-8 border-4 border-blue-400 border-t-transparent rounded-full animate-spin"></div>
            </div>
          ) : error ? (
            <div className="flex justify-center items-center h-full p-4 text-red-500">
              {error}
            </div>
          ) : isMarkdown ? (
            <div className="h-full bg-white dark:bg-gray-900 overflow-auto" style={{ height: 'calc(90vh - 80px)' }}>
              <MarkdownViewer content={code} />
            </div>
          ) : (
            <div className="h-full bg-gray-50 dark:bg-gray-800 flex flex-col">
              <div className="overflow-auto flex-grow" style={{ height: 'calc(90vh - 80px)' }}>
                <pre className="p-4 min-w-full w-max">
                  <code ref={codeRef} className={`text-sm block ${language ? `language-${language}` : ''}`}>
                    {code}
                  </code>
                </pre>
              </div>
            </div>
          )}
        </div>
        
        {showAiChat && (
          <div className="w-1/2 border-l border-gray-200 dark:border-gray-700 overflow-auto" style={{ height: 'calc(90vh - 60px)' }}>
            <AIChatStream
              repoUrl={repoUrl || fileUrl.replace(/\/blob\/[^/]+\/.*$/, '')} // 优先使用传入的repoUrl，否则从fileUrl提取
              selectedCode={code}
              onClose={() => setShowAiChat(false)}
            />
          </div>
        )}
      </div>
    </div>
  );
} 